#include "ftp_uploader.h"
#include <filesystem>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <ctime>
#include <vector>
#include <fstream>
#include <map>
#include <string>
#include <algorithm>

namespace fs = std::filesystem;

static std::string current_time_dirname_minute() {
    std::time_t t = std::time(nullptr);
    std::tm tm = *std::localtime(&t); // copy, safe
    std::ostringstream oss;
    oss << std::put_time(&tm, "%Y-%m-%d-%H-%M");
    return oss.str();
}

static void collectFilesRecursively(const fs::path& baseDir,
                                    const fs::path& cur,
                                    std::vector<std::pair<std::string,std::string>>& out) {
    for (const auto& e : fs::directory_iterator(cur)) {
        try {
            if (e.is_directory()) {
                collectFilesRecursively(baseDir, e.path(), out);
            } else if (e.is_regular_file()) {
                std::string localPath = e.path().string();
                fs::path rel;
                try {
                    rel = fs::relative(e.path(), baseDir);
                } catch (...) {
                    rel = e.path().filename();
                }
                out.emplace_back(localPath, rel.generic_string());
            }
        } catch (const std::exception& ex) {
            std::cerr << "scan error for " << e.path().string() << " : " << ex.what() << "\n";
        }
    }
}

std::map<std::string, std::string> parseConfigFile(const std::string& filename) {
    std::map<std::string, std::string> config;
    std::ifstream file(filename);
    std::string line;
 
    while (std::getline(file, line)) {
        // 跳过注释和空行
        if (line.empty() || line[0] == '#') continue;
 
        // 查找冒号
        size_t colonPos = line.find(':');
        if (colonPos == std::string::npos) continue;
 
        // 提取键和值
        std::string key = line.substr(0, colonPos);
        std::string value = line.substr(colonPos + 1);
 
        // 去除键和值两端的空白字符
        key.erase(0, key.find_first_not_of(" \t"));
        key.erase(key.find_last_not_of(" \t") + 1);
        value.erase(0, value.find_first_not_of(" \t\n\r"));
        value.erase(value.find_last_not_of(" \t\n\r") + 1);
 
        // 存入 map
        config[key] = value;
    }
 
    return config;
}

auto getOrDefault = [](const std::map<std::string, std::string>& m, const std::string& key, const std::string& defaultValue) {
    auto it = m.find(key);
    return (it != m.end()) ? it->second : defaultValue;
};


int main() {

    //     std::string ftp_url  = "ftp://192.168.3.81/Test";
    // std::string ftp_user = "ftpuser";
    // std::string ftp_pass = "taifangftp";
    // std::string local_dir = "data";

    auto config = parseConfigFile("Config.cfg");
    // std::cout << "Get Parsed config:\n";
    std::string ftp_url = getOrDefault(config, "baseUrl", "ftp://192.168.3.81/Test");
    std::string ftp_user = getOrDefault(config, "ftpuser", "ftpuser");
    std::string ftp_pass = getOrDefault(config, "password", "taifangftp");
    std::string local_dir = getOrDefault(config, "uploadDir", "./data/ftpData");
    std::string reportFile = getOrDefault(config, "reportFile", "./report.csv");

    std::string remote_subdir = current_time_dirname_minute();
    std::string remote_base = ftp_url;
    if (!remote_base.empty() && remote_base.back() != '/') remote_base += '/';
    remote_base += remote_subdir; // ftp://host/Test/2025-08-06-20-00

    std::vector<std::pair<std::string,std::string>> filePairs;
    fs::path base = fs::absolute(local_dir);
    if (!fs::exists(base) || !fs::is_directory(base)) {
        std::cerr << "local_dir invalid: " << base.string() << "\n";
        return 1;
    }
    collectFilesRecursively(base, base, filePairs);
    for (int i = 0; i < filePairs.size(); i++) {
        std::cout << "Check Files: " << filePairs.at(i).first << std::endl;;
    }

    if (filePairs.empty()) {
        std::cout << "no files found under " << local_dir << "\n";
        return 0;
    }

    int desired_threads = 10;
    //int thread_count = static_cast<int>(std::max<size_t>(filePairs.size(), static_cast<size_t>(desired_threads)));
    int thread_count = filePairs.size();
    // std::cout << "Found: " << filePairs.size() << " files, using: " << thread_count << " threads.\n";
    if (thread_count <= 0) thread_count = 1;

    FtpUploader uploader(ftp_user, ftp_pass, remote_base, filePairs, reportFile, thread_count);
    uploader.run();

    return 0;
}
